import sys
import time
import tracemalloc


class OrderWithDict:
    def __init__(self, order_id, symbol, price, quantity):
        self.order_id = order_id
        self.symbol = symbol
        self.price = price
        self.quantity = quantity


class OrderWithSlots:
    __slots__ = ["order_id", "symbol", "price", "quantity"]

    def __init__(self, order_id, symbol, price, quantity):
        self.order_id = order_id
        self.symbol = symbol
        self.price = price
        self.quantity = quantity


def measure_memory_and_speed(cls, n_objects=1_000_000):
    # 启动内存跟踪
    tracemalloc.start()

    # 创建对象
    start_time = time.time()
    objects = [cls(i, "BTC", 30000, 1) for i in range(n_objects)]
    creation_time = time.time() - start_time

    # 测量内存
    current, peak = tracemalloc.get_traced_memory()
    tracemalloc.stop()

    # 测试属性访问速度
    start_time = time.time()
    for obj in objects:
        _ = obj.order_id
        _ = obj.symbol
        _ = obj.price
        _ = obj.quantity
    access_time = time.time() - start_time

    return {
        "内存占用(MB)": peak / 1024 / 1024,
        "对象创建时间(秒)": creation_time,
        "属性访问时间(秒)": access_time,
    }


def main():
    # 测试普通类
    print("测试普通类:")
    dict_results = measure_memory_and_speed(OrderWithDict)
    for k, v in dict_results.items():
        print(f"{k}: {v:.2f}")

    print("\n测试使用 __slots__ 的类:")
    slots_results = measure_memory_and_speed(OrderWithSlots)
    for k, v in slots_results.items():
        print(f"{k}: {v:.2f}")

    # 计算差异百分比
    print("\n性能提升:")
    for k in dict_results:
        improvement = (dict_results[k] - slots_results[k]) / dict_results[k] * 100
        print(f"{k}: 提升 {improvement:.1f}%")

    # 展示单个对象的大小差异
    normal_obj = OrderWithDict(1, "BTC", 30000, 1)
    slots_obj = OrderWithSlots(1, "BTC", 30000, 1)
    print(f"\n单个对象大小对比:")
    print(f"普通对象: {sys.getsizeof(normal_obj)} bytes")
    print(f"普通对象的__dict__: {sys.getsizeof(normal_obj.__dict__)} bytes")
    print(
        f"普通对象总大小: {sys.getsizeof(normal_obj) + sys.getsizeof(normal_obj.__dict__)} bytes"
    )
    print(f"Slots对象: {sys.getsizeof(slots_obj)} bytes")
    try:
        print(f"Slots对象的__dict__: {sys.getsizeof(slots_obj.__dict__)} bytes")
    except AttributeError as e:
        print(f"Slots对象没有__dict__属性：{e}")


if __name__ == "__main__":
    main()
